﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace WooCoo.ObjectModel.ManagedProperty.PropertyDescriptors
{
    /// <summary>
    /// ManagedPropertyObject 的 PropertyDescriptor 容器
    /// </summary>
    internal static class PropertyDescriptorFactory
    {
        private static Dictionary<PropertyInfoSet, PropertyDescriptorCollection> _allProperties =
            new Dictionary<PropertyInfoSet, PropertyDescriptorCollection>();

        internal static PropertyDescriptorCollection GetProperties(ManagedPropertyBase managedObj)
        {
            PropertyDescriptorCollection result = null;

            var propertyInfoSet = managedObj.Properties;
            if (!_allProperties.TryGetValue(propertyInfoSet, out result))
            {
                lock (_allProperties)
                {
                    if (!_allProperties.TryGetValue(propertyInfoSet, out result))
                    {
                        result = FindProperties(managedObj);

                        //添加到集合中。
                        _allProperties.Add(propertyInfoSet, result);                        
                    }
                }
            }

            return result;
        }

        private static PropertyDescriptorCollection FindProperties(ManagedPropertyBase managedObj)
        {
            //加入 ManagedProperty
            var mpList = managedObj.Properties.GetProperties();
            var pdList = mpList.Select(mp => new ManagedPropertyDescriptor(mp) as PropertyDescriptor).ToList();

            //加入 CLRProperty
            //为了兼容一些直接使用 CLR 属性而没有使用托管属性编写的视图属性。
            var clr = managedObj.GetType().GetProperties();
            foreach (var clrProperty in clr)
            {
                if (mpList.All(mp => mp.Name != clrProperty.Name))
                {
                    pdList.Add(new CLRPropertyDescriptor(clrProperty));
                }
            }

            return new PropertyDescriptorCollection(pdList.ToArray());
        }      
    }
}
